package com.jacky.webflux.jwt.token;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class JwtTokenComponent {


    final private JwtProperties properties;

    public JwtTokenComponent(JwtProperties properties) {
        this.properties = properties;
    }

    public String generateToken(TokenUser user) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", user.getRoles().stream().map(Enum::name).collect(Collectors.toSet()));
        return doGenerateToken(claims, user.getUsername());
    }

    private String doGenerateToken(Map<String, Object> claims, String userName) {
        final Date now = new Date();
        final Date expiredAt = new Date(now.getTime() + properties.getExpiration() * 1000);

        Key key = Keys.hmacShaKeyFor(properties.getSecret().getBytes(StandardCharsets.UTF_8));
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userName)
                .setIssuedAt(now)
                .setIssuer(properties.getIssuer())
                .setExpiration(expiredAt)
                .signWith(key)
                .compact();
    }

    public Boolean isTokenExpired(String token) {
        return tokenExpiredAt(token).before(new Date());
    }

    public Date tokenExpiredAt(String token) {
        Claims claims = this.getClaimsFromToken(token);
        return claims.getExpiration();
    }

    public Claims getClaimsFromToken(String token) {
        Key key = Keys.hmacShaKeyFor(properties.getSecret().getBytes(StandardCharsets.UTF_8));
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}
